package sf.dsl.example;

import sf.database.dialect.DBDialect;
import sf.database.jdbc.sql.SQLContext;
import sf.database.jdbc.sql.SQLParameter;
import sf.spring.util.CollectionUtils;
import sf.tools.ArrayUtils;
import sf.tools.StringUtils;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * with子句
 */
public class WithBuilder {
    protected List<WithOne> withOneList;
    protected boolean recursive;

    public WithBuilder() {
        this.withOneList = new LinkedList<>();
    }

    public WithBuilder recursive(boolean recursive) {
        this.recursive = recursive;
        return this;
    }

    public WithBuilder add(WithOne withOne) {
        withOneList.add(withOne);
        return this;
    }

    protected void toSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean mustTableAlias, DBDialect dialect) {
        sb.append("with ").append(recursive ? "RECURSIVE " : "");
        boolean f1 = false;
        for (WithOne w : withOneList) {
            if (f1) {
                sb.append(',');
            }
            f1 = true;
            String alias = w.alias;
            if (dialect != null) {
                alias = dialect.wrapKeyword(alias);
            }
            sb.append(alias).append(" AS ");
            if (ArrayUtils.isNotEmpty(w.simpleFields)) {
                sb.append('(');
                boolean f2 = false;
                for (int i = 0; i < w.simpleFields.length; i++) {
                    if (f2) {
                        sb.append(',');
                    }
                    f2 = true;
                    w.simpleFields[i].toConditionSql(sb, list, mustTableAlias, true, dialect);
                }
                sb.append(')');
            }
            sb.append('(');
            if (w.subQuery != null) {
                w.subQuery.dialect = dialect;
                SQLContext sqlContext = ExampleSQL.getSelectSQLContext(w.subQuery, null, SelectOpt.all, true);
                if (CollectionUtils.isNotEmpty(sqlContext.getParas())) {
                    list.addAll(sqlContext.getParas());
                }
                if (StringUtils.isNotBlank(sqlContext.getSql())) {
                    sb.append(sqlContext.getSql());
                }
            }
            sb.append(')');
        }
    }

    public static class WithOne {
        protected String alias;
        protected SimpleField[] simpleFields;
        protected Example subQuery;

        public WithOne(String alias, SimpleField[] simpleFields, Example subQuery) {
            this.alias = alias;
            this.simpleFields = simpleFields;
            this.subQuery = subQuery;
        }
    }
}
